#include "main.h"
#include "uart.h"

static uint8_t uart_buf_tx[UART_NUM][UART_MAXBUFFLEN] = {0};
static uint8_t uart_buf_rx[UART_NUM][UART_MAXBUFFLEN] = {0};

// 串口结构体
static uart_t uarts[] = {
    {
        UART_HT,
        115200u,
        UART_MAXBUFFLEN,
        UART_MAXBUFFLEN,
        false,
        false,
        {0},
        {0},
        {0},
    },
};

static void uart_idle_callback(void *arg);

void uart_init(void)
{
    { /* Enable peripheral clock of AFIO, UxART */
        CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
        CKCUClock.Bit.AFIO                   = 1;
        CKCUClock.Bit.UART0                  = 1;
        CKCU_PeripClockConfig(CKCUClock, ENABLE);
    }
    //手动添加代码
    AFIO_GPxConfig(UART_AF_PORT, UART_Tx_AF_PIN, AFIO_FUN_USART_UART);
    AFIO_GPxConfig(UART_AF_PORT, UART_Rx_AF_PIN, AFIO_FUN_USART_UART);
    NVIC_EnableIRQ(UART0_IRQn);
    
    for(int i = 0;i < UART_NUM;i++)//配置初始化
    {
        USART_InitTypeDef USART_InitStructure = {0};
        USART_InitStructure.USART_BaudRate = uarts[i].baud;
        USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
        USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
        USART_InitStructure.USART_Parity = USART_PARITY_NO;
        USART_InitStructure.USART_Mode = USART_MODE_NORMAL;

        USART_Init(uarts[i].regs, &USART_InitStructure);
        USART_IntConfig(uarts[i].regs,USART_INT_RXDR,ENABLE);
        USART_TxCmd(uarts[i].regs, ENABLE);
        USART_RxCmd(uarts[i].regs, ENABLE);
    }
    for (int i = 0; i < UART_NUM; i++)//缓冲区初始化
    {
        if (uarts[i].fifo_txlen) {
            bfifo_init(&uarts[i].fifo_tx, (uint8_t *)uart_buf_tx[i], uarts[i].fifo_txlen);
        }
        if (uarts[i].fifo_rxlen) {
            bfifo_init(&uarts[i].fifo_rx, (uint8_t *)uart_buf_rx[i], uarts[i].fifo_rxlen);
        }
    }
    for (int i = 0; i < UART_NUM; i++)//idle timer init
    {   
        TimerInit(&uarts[i].uart_idle,3 - 1,TIMER_MODE_ONE_SHOT,uart_idle_callback,UART_NUM-1);
    }
}

/**
 * @brief  读串口忙状态
 * @param  chn：串口号
 */
bool is_uart_busy(uint8_t chn)
{
    param_assert(chn < UART_NUM);
    
    uart_t *uart = uarts + chn;
    return (uart->tx_busy);
}

/**
 * @brief  从串口发送数据
 * @param  chn：串口号
 * @param  dat：数据指针
 * @param  size：数据长度
 */
int uart_send(uint8_t chn, const void *dat, int size)
{
    uart_t *uart = uarts + chn;

    param_assert(chn < UART_NUM);
    size = bfifo_in((&uart->fifo_tx), dat, size);  // 数据写入发送缓冲区，由中断自行取出发送

    if (uart->tx_busy == false) {
        uart->tx_busy = true;
        // 开发送完成中断
        USART_IntConfig(uarts->regs,USART_INT_TXDE | USART_INT_TXC, ENABLE);
    }
    return size;
}

/**
 * @brief  从串口接收数据
 * @param  chn：串口号
 * @param  bytes-数据指针
 * @param  len：数据长度
 */
int uart_recv(uint8_t chn, void *dat, int size)
{
    uart_t *uart = uarts + chn;
    param_assert(chn < UART_NUM);
    return bfifo_out((&uart->fifo_rx), dat, size);
}

/**
 * @brief  串口中断处理
 * @param  chn:串口通道号
 */
static void uart_irq_handler(uart_chn chn)
{
    uart_t *uart = uarts + chn;  // 获得串口通道
    USART_T regs = uart->regs;   // 获得串口的寄存器地址
    uint8_t byte;

    param_assert(chn < UART_NUM);

    // recive data
    if (USART_GetFlagStatus(regs, USART_FLAG_RXDR))
    {
        byte = USART_ReceiveData(regs);
        // USART_SendData(regs, byte);
        bfifo_in_byte(&uart->fifo_rx, byte);     
        //idle timer
        if(!uart->rx_busy)
            TimerStart(&uart->uart_idle);
    }

    // send data
    if (USART_GetIntStatus(regs, USART_INT_TXDE) &&
        USART_GetFlagStatus(regs, USART_FLAG_TXDE))
    {
        // 从发送缓冲区读出
        if (bfifo_out_byte(&uart->fifo_tx, &byte)) 
        {
            USART_SendData(regs, byte);
        }
        else 
        {
            uart->tx_busy = false;
            USART_IntConfig(regs, USART_INT_TXDE, DISABLE);
        }
    }

    //send data complete
    if (USART_GetIntStatus(regs, USART_INT_TXC) &&
        USART_GetFlagStatus(regs, USART_FLAG_TXC))
    {
        USART_IntConfig(regs, USART_INT_TXC, DISABLE);
    }
}

void UART0_IRQHandler(void)
{
    uart_irq_handler(UART_COM);
}

/**printf retarge**/
int fputc(int ch, FILE *f)
{
    UART_HT->DR = (u8)ch;
    while ((UART_HT->SR & USART_FLAG_TXC) == RESET);
    return ch;
}

/**
	* @brief  串口数据读取
    * @param  chn:串口通道号
	*/
static void _uart_proc(uint8_t chn)
{
    int to_read;

    if(!uarts[chn].rx_busy){
        return;
    } else{
        uarts[chn].rx_busy = false;
    }
    
    uint8_t buff[UART_MAXBUFFLEN];
    
    to_read = (&uarts[chn].fifo_rx != NULL) ? bfifo_len(&uarts[chn].fifo_rx) : 0;
    if (to_read > 0)
    {
        to_read = sys_min(to_read, 32);
        if (to_read != (bfifo_out(&uarts[chn].fifo_rx, buff, to_read)))
        {
            ;
        }
        processCommand(buff);//command paser
    }

    return;
}

/**
	* @brief  串口函数流程
	*/
static void uart_idle_callback(void *arg)
{
	uart_t *uart = uarts + (int )arg;  // 获得串口通道
    if(!uart->rx_busy)
        uart->rx_busy = true;
}

/**
	* @brief  串口函数流程
	*/
void uart_proc(void)
{
    for (int i = 0; i < UART_NUM; i++)
    {
        _uart_proc(i);
    } 
}

void uart_test(void)
{
    uart_send(UART_COM,"this is command test...\n",24);
}
